﻿using System;
using System.Collections.Generic;
using System.IO;
using CI.Interfaces;
using CI.Mesopotamia.WebService;
using CI.Utils;

namespace CI.Mesopotamia
{
    /// <summary>
    /// Factory Design pattern to get a scenario object
    /// Can create a an instance of several derived classes depending on factors, eg network(grid server) access....
    /// </summary>
    public class ScenarioFactory
    {

        // classes
        private readonly ScenarioGrid _sg = new ScenarioGrid();
        private readonly ScenarioLocalXML _sxml = new ScenarioLocalXML();
        private readonly SimEnv _simEnv = SimEnv.Instance;


        /// <summary>
        /// get a scenario
        /// </summary>
        /// <returns></returns>
        public IScenario GetScenario()
        {
            _simEnv.TraceLogger.LogDebug("GetScenario - Start");
            IScenario scenario;

            // if the grid is online use it
            if (ScenarioGrid.GridOnline())
            {
                scenario = _sg;
            }
            // else use local 
            else
            {
                scenario = _sxml;
            }

            _simEnv.TraceLogger.LogDebug("GetScenario - Finish");
            return scenario;

        }

        /// <summary>
        /// Get the Preferred scenario
        /// </summary>
        /// <returns>scenario name</returns>
        public string GetPreferredScenarioName()
        {
            _simEnv.TraceLogger.LogDebug("GetPreferredScenarioName - Start");

            // if the grid is online            
            var result = ScenarioGrid.GridOnline() ? GetPreferredScenarioNameFromGrid() : GetPreferredScenarioNameFromLocalResources();

            _simEnv.TraceLogger.LogDebug("Preferred Scenario - " + result);
            _simEnv.TraceLogger.LogDebug("GetPreferredScenarioName - Finish");
            return result;
        }

        public string GetPreferredScenarioNameFromLocalResources()
        {
            string result = null;

            _simEnv.TraceLogger.LogDebug("Getting grid from local availablity");
            // get the most recent written scenario file
            var dfi = new DirectoryInfo(ResourceFolders.UsersResourceFolder());
            var files = dfi.GetFiles(string.Format("*{0}", Globals.ScenarioMatch));

            // if we found some files
            if (files != null)
            {
                // date comparison
                var dateCompare = new DateCompare();
                // sort them
                Array.Sort(files, dateCompare);
                // set the last one as what we want
                result = files[0].Name.ToLower().Replace(Globals.ScenarioMatch, "");
            }
            return result;
        }

        private string GetPreferredScenarioNameFromGrid()
        {
            string result = null;
            _simEnv.TraceLogger.LogDebug("Requesting Preferred sceanrio from grid");
            var ibc = new InboundClient();
#if (DEBUG&&GRIDLOCAL)
            // if debug use the local endpoint for debugging
            ibc.Endpoint.Address = new System.ServiceModel.EndpointAddress("http://localhost/MesopotamiaDCProxy/inbound.svc");
#endif
            try
            {
                result = ibc.GetPreferredScenario(_sg.HostingEnvironmentVersionInformation, Properties.Settings.Default.UserID).Trim();
            }
            catch (Exception ex)
            {
                _simEnv.TraceLogger.LogDebug("Exception getting prefered scenario" + ex.Message);
            }
            finally
            {
                ibc.Close();
            }
            return result;
        }

        /// <summary>
        /// Do a date comparison of the values
        /// </summary>
        private sealed class DateCompare : IComparer<FileInfo>
        {
            /// <summary>
            /// Compare the file dates
            /// http://www.johnbatdorf.net/blog/NETSortingFilesByDate.aspx
            /// </summary>
            /// <param name="fileInfo1"></param>
            /// <param name="fileInfo2"></param>
            /// <returns></returns>
            public int Compare(FileInfo fileInfo1, FileInfo fileInfo2)
            {
                var date1 = fileInfo1 == null ? Convert.ToDateTime(System.Data.SqlTypes.SqlDateTime.Null) : fileInfo1.LastWriteTime;
                var date2 = fileInfo2 == null ? Convert.ToDateTime(System.Data.SqlTypes.SqlDateTime.Null) : fileInfo2.LastWriteTime;

                if (date1 > date2) return -1;
                if (date1 < date2) return +1;
                return 0;
            }
        }
    }
}